package com.sbp.message.consumer;

import com.alibaba.fastjson.JSON;
import com.dap.api.ISunriseService;
import com.dap.exception.PlatformException;
import com.dap.param.ControlData;
import com.dap.param.GeneratePlatformCtrlDataInterface;
import com.dap.param.StringInput;
import com.dap.utils.ReflectUtil;
import com.dap.utils.SpringUtils;
import com.google.common.collect.Maps;
import com.sbp.message.annotation.MessageConsumerAnnotation;
import com.sbp.message.api.entity.Message;
import com.sbp.message.entity.SunriseServiceAndParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.*;

public class ConsumerServicesManager implements InitializingBean,ApplicationContextAware {
    private static final Logger logger = LoggerFactory.getLogger(ConsumerServicesManager.class);
    public static class ServiceAndMetadata {
        public final ISunriseService<StringInput> service;
        public final boolean exclusive;
        public ServiceAndMetadata(ISunriseService<StringInput> service, boolean exclusive) {
            this.service = service;
            this.exclusive = exclusive;
        }
    }

    private String appName;
    public void setAppName(String appName) {
        this.appName = appName;
    }


    public SunriseServiceAndParam resolveSunriseServiceAndParam(Message message, String group) {
        Map<String, ServiceAndMetadata> groupMap = topicGroupMap.get(message.getDestination());
        if (null == groupMap || groupMap.isEmpty()) {
            logger.warn("message has no service, message=\n{}", JSON.toJSONString(message));
            return null;
        }
        ServiceAndMetadata serviceAndMetadata = groupMap.get(group);
        if (null == serviceAndMetadata) {
            logger.warn("message has no service, message=\n{}", JSON.toJSONString(message));
            return null;
        }

        ControlData controlData = generateControlData();
        StringInput stringInput = new StringInput(controlData, message.getContent());

        return new SunriseServiceAndParam(serviceAndMetadata.service, stringInput);
    }

    private ControlData generateControlData() {
        GeneratePlatformCtrlDataInterface gpcdi = SpringUtils.getBean(GeneratePlatformCtrlDataInterface.class);
        if (gpcdi != null) {
            return gpcdi.generate("message");
        } else {
            ControlData controlData = new ControlData();
            controlData.setInternalRequestSource("message");
            return controlData;
        }
    }


    private Map<String, Map<String, ServiceAndMetadata>> topicGroupMap = null;
    public Map<String, Map<String, ServiceAndMetadata>> resolveTopicGroupMap() {
        if (topicGroupMap != null) {
            return topicGroupMap;
        }

        topicGroupMap = Maps.newHashMap();

        if (this.applicationContext == null) {
            return topicGroupMap;
        }

        // 获取有注解的实例
        Map<String, Object> beansWithAnnotationMap = this.applicationContext.getBeansWithAnnotation(MessageConsumerAnnotation.class);

        for(Map.Entry<String, Object> entry : beansWithAnnotationMap.entrySet()) {
            ISunriseService<StringInput> serviceInstance = (ISunriseService<StringInput>) entry.getValue();
            serviceInstance = (ISunriseService<StringInput>) ReflectUtil.getBeanTargetIfGlib(serviceInstance);

            MessageConsumerAnnotation[] annotations = serviceInstance.getClass().getAnnotationsByType(MessageConsumerAnnotation.class);
            if (annotations != null && annotations.length > 0) {
                for (MessageConsumerAnnotation annotation : annotations) {
                    final String consumerGroup = resolveConsumerGroup(annotation);
                    for (String topic : annotation.topics()) {
                        Map<String, ServiceAndMetadata> groupMap = topicGroupMap.get(topic);
                        if (null == groupMap) {
                            groupMap = Maps.newHashMap();
                            topicGroupMap.put(topic, groupMap);
                        }

                        ServiceAndMetadata preServiceAndMetadata = groupMap.get(consumerGroup);
                        if (preServiceAndMetadata != null) {
                            throw new PlatformException("topic=" + topic + ", group=" + consumerGroup
                                                        + ", duplicate consumers, classes="
                                                        + preServiceAndMetadata.service.getClass().getName()
                                                        + ", "
                                                        + serviceInstance.getClass().getName());
                        }

                        groupMap.put(consumerGroup, new ServiceAndMetadata(serviceInstance, annotation.exclusive()));
                    }
                }
            } else {
                throw new PlatformException(entry.getKey() + " has MessageConsumerAnnotation, but cannot get");
            }
        }

        return topicGroupMap;
    }
    private String resolveConsumerGroup(MessageConsumerAnnotation annotation) {
        if (StringUtils.isEmpty(annotation.group())) {
            return appName;
        } else {
            return annotation.group();
        }
    }



    @Override
    public void afterPropertiesSet() throws Exception {
        resolveTopicGroupMap();
        logger.info("topicGroupMap={}", JSON.toJSONString(topicGroupMap));
    }

    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

}
